use std::time::Duration;

use steamworks::{AppIDs, AppId, Client, PublishedFileId, SteamError, UGCQueryType, UGCType};

use crate::{
    models::{
        item::{ItemInfo, Pagination},
        statistic::StatisticInfo,
    },
    utils::utils::wait_for_response,
};

// 获取单个Item数据
pub fn get_item(id: u64, client: Client) -> Result<ItemInfo, String> {
    let (tx, rx) = std::sync::mpsc::channel();

    let query = client
        .ugc()
        .query_item(PublishedFileId(id))
        .expect("Failed to query item")
        .include_children(true)
        .include_long_desc(true);
    query.fetch(move |res| {
        let _ = tx.send(match res {
            Ok(item) => {
                let statistics: StatisticInfo = StatisticInfo::new(0, &item);
                match item.get(0) {
                    Some(item_data) => {
                        let children: Vec<u64> = item
                            .get_children(0)
                            .map(|v| v.iter().map(|i| i.0).collect())
                            .unwrap_or_default();
                        Ok(ItemInfo::new(statistics, item_data).set_children(children))
                    }
                    None => Err(SteamError::NoMatch),
                }
            }
            Err(err) => Err(err),
        });
    });
    wait_for_response(rx, client, 20, Duration::from_millis(100))
}

// 获取多个Item数据
pub fn get_items(ids: Vec<u64>, client: Client) -> Result<Vec<ItemInfo>, String> {
    let (tx, rx) = std::sync::mpsc::channel();
    let query = client
        .ugc()
        .query_items(
            ids.iter()
                .map(|id| PublishedFileId(*id))
                .collect::<Vec<_>>(),
        )
        .expect("Failed to query items")
        .include_long_desc(true);

    query.fetch(move |res| {
        let mut items_list = Vec::new();
        let send_result = match res {
            Ok(items) => {
                for (index, query) in items.iter().enumerate() {
                    if let Some(item) = query {
                        let statistics = StatisticInfo::new(index, &items);
                        items_list.push(ItemInfo::new(statistics, item));
                    }
                }
                Ok(items_list)
            }
            Err(err) => Err(err),
        };
        let _ = tx.send(send_result);
    });

    wait_for_response(rx, client, 20, Duration::from_millis(100))
}

// 分页获取所有Item数据
pub fn get_all(
    page: u32,
    app_id: u32,
    client: Client,
) -> Result<Pagination<Vec<ItemInfo>>, String> {
    let (tx, rx) = std::sync::mpsc::channel();
    let query = client
        .ugc()
        .query_all(
            UGCQueryType::RankedByVote,
            UGCType::ItemsReadyToUse,
            AppIDs::CreatorAppId(AppId(app_id)),
            page,
        )
        .expect("Failed to query all")
        .include_long_desc(true);

    query.fetch(move |res| {
        let mut items_list = Vec::new();
        let send_result = match res {
            Ok(items) => {
                for (index, query) in items.iter().enumerate() {
                    if let Some(item_query) = query {
                        let statistics = StatisticInfo::new(index, &items);
                        items_list.push(ItemInfo::new(statistics, item_query));
                    }
                }
                Ok(Pagination {
                    page,
                    size: items.returned_results(),
                    total: items.total_results(),
                    items: items_list,
                })
            }
            Err(err) => Err(err),
        };
        let _ = tx.send(send_result);
    });

    wait_for_response(rx, client, 50, Duration::from_millis(100))
}

// 分页获取所有合集数据
pub fn get_collections(
    page: u32,
    app_id: u32,
    client: Client,
) -> Result<Pagination<Vec<ItemInfo>>, String> {
    let (tx, rx) = std::sync::mpsc::channel();
    let query = client
        .ugc()
        .query_all(
            UGCQueryType::RankedByVote,
            UGCType::Collections,
            AppIDs::ConsumerAppId(AppId(app_id)),
            page,
        )
        .expect("Failed to query collections")
        .include_long_desc(true)
        .include_children(true);

    query.fetch(move |res| {
        let mut items_list = Vec::new();
        let send_result = match res {
            Ok(items) => {
                for (index, query) in items.iter().enumerate() {
                    if let Some(item_query) = query {
                        let children: Vec<u64> = items
                            .get_children(0)
                            .map(|v| v.iter().map(|i| i.0).collect())
                            .unwrap_or_default();
                        let statistics = StatisticInfo::new(index, &items);
                        items_list
                            .push(ItemInfo::new(statistics, item_query).set_children(children));
                    }
                }
                Ok(Pagination {
                    page,
                    size: items.returned_results(),
                    total: items.total_results(),
                    items: items_list,
                })
            }
            Err(err) => Err(err),
        };
        let _ = tx.send(send_result);
    });

    wait_for_response(rx, client, 50, Duration::from_millis(100))
}
